#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QCloseEvent>
#include <QTableWidget>
#include <QTableWidgetSelectionRange>
#include <QLabel>
#include <QPushButton>
#include <QString>
#include <QStringList>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include <QTextStream>
#include <QAction>
#include <QTextCodec>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QDebug>
#include <QVariant>
#include "myfinddialog.h"
#include "myreplacedialog.h"
#include "myforecolordialog.h"
#include "mybetweendialog.h"

namespace Ui {
class MainWindow;
}

/**
 * 定义一个节点类
 * 这些节点用于存储合并的单元格的信息
 */
class Node
{
private:
    int startRow;    //合并的起始行号
    int startColumn; //合并的起始列号
    int totalRow;    //合并的总行数
    int totalColumn; //合并的总列数

public:
    Node() : startRow(-1), startColumn(-1), totalRow(0), totalColumn(0) {}

    Node(int _startRow, int _startColumn) :
        startRow(_startRow), startColumn(_startColumn),
        totalRow(1), totalColumn(1) {}

    Node(int _startRow, int _startColumn, int _totalRow, int _totalColumn) :
        startRow(_startRow), startColumn(_startColumn),
        totalRow(_totalRow), totalColumn(_totalColumn) {}

    ~Node() {}

    int get_start_Row()
    {
        return startRow;
    }

    int get_start_Column()
    {
        return startColumn;
    }

    int get_total_Row()
    {
        return totalRow;
    }

    int get_total_Column()
    {
        return totalColumn;
    }

    void set_data(int _startRow, int _startColumn, int _totalRow, int _totalColumn)
    {
        startRow = _startRow;
        startColumn = _startColumn;
        totalRow = _totalRow;
        totalColumn = _totalColumn;
    }

    friend bool operator ==(const Node &a, const Node &b)
    {
        return (a.startRow == b.startRow) && (a.startColumn == b.startColumn);
    }

    friend QDataStream &operator <<(QDataStream &output, const Node &node)
    {
        return output << node.startRow << node.startColumn << node.totalRow << node.totalColumn;
    }

    friend QDataStream &operator >>(QDataStream &input, Node &node)
    {
        int _startRow, _startColumn, _totalRow, _totalColumn;
        input >> _startRow >> _startColumn >> _totalRow >> _totalColumn;
        node.set_data(_startRow, _startColumn, _totalRow, _totalColumn);
        return input;
    }
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:

    explicit MainWindow(QWidget *parent = 0);

    ~MainWindow();

private slots:

    //新建空表格
    void new_table();

    //打开文件
    void open_file();

    //保存文件
    bool save_file();

    //文件另存为
    bool copy_file();

    //检查是否保存，返回值为是否继续操作
    bool check_save();

    //窗口关闭
    void closeEvent(QCloseEvent *event);

    //数据排序
    void upsort_data();
    void downsort_data();

    //数据查找
    void search_dialog();
    void search_next(const QString &text);
    void search_all(const QString &text);

    //数据替换
    void replace_dialog();
    void replace_next(const QString &find_text, const QString &replace_text);
    void replace_all(const QString &find_text, const QString &replace_text);

    //数据求和
    void sum_data();

    //数据求平均
    void aver_data();

    //合并单元格
    void merge_item();

    //拆分单元格
    void split_item();

    //检查单元格数据，通常发生在输入数据后
    void item_input(int row, int column);

    //当前选择单元格改变的槽函数
    void item_changed(int currentRow, int currentColumn);

    //对合并拆分影响太大，搁置
    /*
    void remove_row();

    void remove_column();
    */

    //隐藏行
    void hide_row();

    //隐藏列
    void hide_column();

    //显示隐藏行
    void show_row();

    //显示隐藏列
    void show_column();

    //void mousePressEvent(QMouseEvent *event) override;
    //void mouseReleaseEvent(QMouseEvent *event) override;

    //设置单元格外观颜色
    void edit_forecolor();
    void set_forecolor(const QString &text);//设置字体颜色
    void set_backcolor(QString text);       //设置背景颜色

    //设置单元格
    void set_bold(int arg1);               //设置为粗体或取消粗体
    void set_italy(int arg1);              //设置为斜体或取消斜体
    void set_fonts(const QString &text);   //设置为选中的字体
    void set_fontsize(const QString &arg1);//设置为选中的字号
    void set_fontleft();                   //设置为居左
    void set_fontmid();                    //设置为居中
    void set_fontright();                  //设置为居右
    void set_type(const QString &arg1);    //设置为选中的类型

    //筛选
    void select_equal();   //筛选中的等于
    void select_nonequal();     //筛选中的不等于
    void select_upequal();      //筛选中的大于等于
    void select_downequal();    //筛选中的小于等于
    void select_upaver();   //筛选中的大于平均值
    void select_downaver();     //筛选中的小于平均值
    void dialog_between();      //打开筛选中的介于的对话框
    void select_between(double min, double max);  //筛选中的介于某范围内
    void eliminate();

private:
    enum ItemType{General = 0, String, Number, date};
    //枚举值是从0开始，与类型名字符串列表type_name的起始下标相同

    //检查字符串类型
    ItemType check_type(const QString &str);

    //打开文本文件
    void open_txt_file(const QString &FileName);

    //打开自定义二进制文件
    void open_stm_file(const QString &FileName);

    //保存文本文件
    bool save_txt_file(const QString &FileName);

    //保存自定义二进制文件
    bool save_stm_file(const QString &FileName);

private:
    Ui::MainWindow *ui;
    QString filename;       //记录当前文件
    bool save_flag;         //记录是否保存
    QLabel *labItemIndex;   //状态栏上显示单元格的行号、列号
    QLabel *labItemType;    //状态栏上显示单元格的类型
    const QStringList type_name = {"常规", "文本", "数值", "日期"};
    QList<Node> merge_list;
};

#endif // MAINWINDOW_H
